#include "book.h"
#include "tcpclient.h"
#include<QInputDialog> //专门用于输入
#include<QMessageBox>
#include<QFileDialog>
#include"opewidget.h"
#include"sharefile.h"

Book::Book(QWidget *parent) : QWidget(parent)
{
    m_strEnterDir.clear();

    m_bDownload=false;
    m_pTimer=new QTimer;
    m_pBookListW=new QListWidget;

    m_pReturnPB=new QPushButton("返回");
    m_pCreateDirPB=new QPushButton("创建文件夹");
    m_pDelDirPB=new QPushButton("删除文件夹");
    m_pRenamePB=new QPushButton("重命名文件");
    m_pFlushDirPB=new QPushButton("刷新文件夹");

    //五个按钮 水平布局
    QVBoxLayout *pDirVBL=new QVBoxLayout;
    pDirVBL->addWidget(m_pReturnPB);
    pDirVBL->addWidget(m_pCreateDirPB);
    pDirVBL->addWidget(m_pDelDirPB);
    pDirVBL->addWidget(m_pRenamePB);
    pDirVBL->addWidget(m_pFlushDirPB);

    m_pUploadPB=new QPushButton("上传文件");
    m_pDelFilePB=new QPushButton("删除文件");
    m_pDownloadPB=new QPushButton("下载文件");
    m_pShareFilePB=new QPushButton("共享文件");
    m_pMoveFilePB=new QPushButton("移动文件");
    m_SelectDirPB=new QPushButton("目标目录");
    m_SelectDirPB->setEnabled(false);   //默认不可选

    QVBoxLayout *pFileVBL=new QVBoxLayout;
    pFileVBL->addWidget(m_pUploadPB);
    pFileVBL->addWidget(m_pDelFilePB);
    pFileVBL->addWidget(m_pDownloadPB);
    pFileVBL->addWidget(m_pShareFilePB);
    pFileVBL->addWidget(m_pMoveFilePB);
    pFileVBL->addWidget(m_SelectDirPB);

    QHBoxLayout *pMain=new QHBoxLayout;
    pMain->addWidget(m_pBookListW);
    pMain->addLayout(pDirVBL);
    pMain->addLayout(pFileVBL);

    setLayout(pMain);
    //关联 创建目录 信号槽
    connect(m_pCreateDirPB,SIGNAL(clicked(bool)),this,SLOT(createDir()));
    //关联 刷新文件夹 信号槽
    connect(m_pFlushDirPB,SIGNAL(clicked(bool)),this,SLOT(flushFile()));
    //关联 删除文件 信号槽
    connect(m_pDelDirPB,SIGNAL(clicked(bool)),this,SLOT(delDir()));
    //关联 重命名文件 信号槽
    connect(m_pRenamePB,SIGNAL(clicked(bool)),this,SLOT(renameFile()));
    //关联 进入文件夹 信号槽
    connect(m_pBookListW,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(enterDir(QModelIndex)));
    //关联 返回文件夹 信号槽
    connect(m_pReturnPB,SIGNAL(clicked(bool)),this,SLOT(returnPre()));
    //关联 上传文件 信号槽
    connect(m_pUploadPB,SIGNAL(clicked(bool)),this,SLOT(uploadFile()));
    //关联 计时结束后 上传文件数据 信号槽
    connect(m_pTimer,SIGNAL(timeout()),this,SLOT(uploadFileData()));
    //关联 删除常规文件 信号槽
    connect(m_pDelFilePB,SIGNAL(clicked(bool)),this,SLOT(delRegFile()));
    //关联 下载文件 信号槽
    connect(m_pDownloadPB,SIGNAL(clicked(bool)),this,SLOT(downloadFile()));
    //关联 分享文件 信号槽
    connect(m_pShareFilePB,SIGNAL(clicked(bool)),this,SLOT(shareFile()));
    //关联 移动文件 信号槽
    connect(m_pMoveFilePB,SIGNAL(clicked(bool)),this,SLOT(moveFile()));
    //关联 目标目录 信号槽
    connect(m_SelectDirPB,SIGNAL(clicked(bool)),this,SLOT(selectDestDir()));
}

void Book::updateFileList(const PDU *pdu)
{
    //文件列表清除旧的文件
    if(pdu==NULL){
        return;
    }
    QListWidgetItem *pItemTmp;
    int row=m_pBookListW->count();
    while(m_pBookListW->count()>0){
        pItemTmp=m_pBookListW->item(row-1);
        m_pBookListW->removeItemWidget(pItemTmp);
        delete pItemTmp;
        row=row-1;
    }
    //文件列表添加新文件
    FileInfo *pFileInfo=NULL;
    int iCount=pdu->uiMsgLen/sizeof(FileInfo);
    for(int i=0;i<iCount;i++){
        //按地址提取数据
        pFileInfo=(FileInfo*)(pdu->caMsg)+i;
        qDebug()<<pFileInfo->caFileName<<pFileInfo->iFileType;
        QListWidgetItem *pItem=new QListWidgetItem;
        //分类显示
        if(pFileInfo->iFileType==0){
            pItem->setIcon(QIcon(QPixmap(":/map/folder.png")));
        }
        else if(pFileInfo->iFileType==1){
            pItem->setIcon(QIcon(QPixmap(":/map/document.png")));
        }
        pItem->setText(pFileInfo->caFileName);
        m_pBookListW->addItem(pItem);
    }
}

void Book::clearEnterDir(){
    m_strEnterDir.clear();
}

QString Book::enterDir(){
    return m_strEnterDir;
}

void Book::createDir()
{
    //写新文件夹名字
    QString strNewDir = QInputDialog::getText(this,"新建文件夹","新文件夹名字");
    if(!strNewDir.isEmpty()){
        if(strNewDir.size()>32){
            QMessageBox::warning(this,"新建文件夹","新建文件夹名字长度不能超过32");
        }
        else{
            //用户名+新文件夹名 caData  目录 caMsg
            QString strName=TcpClient::getInstance().loginName();
            QString strCurPath=TcpClient::getInstance().curPath();
            PDU *pdu=mkPDU(strCurPath.size()+1);
            pdu->uiMsgType=ENUM_MSG_TYPE_CREATE_DIR_REQUEST;
            strncpy(pdu->caData,strName.toStdString().c_str(),strName.size());
            strncpy(pdu->caData+32,strNewDir.toStdString().c_str(),strNewDir.size());
            memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
            TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
            free(pdu);
            pdu=NULL;
        }
    }
    else{
        QMessageBox::warning(this,"新建文件夹","新文件夹名字不能为空");
    }
}

void Book::flushFile()
{
    QString strCurPath=TcpClient::getInstance().curPath();
    PDU *pdu=mkPDU(strCurPath.size()+1);
    pdu->uiMsgType=ENUM_MSG_TYPE_FLUSH_FILE_REQUEST;
    strncpy((char*)(pdu->caMsg),strCurPath.toStdString().c_str(),strCurPath.size());
    TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
    free(pdu);
    pdu=NULL;
}

void Book::delDir()
{
    QString strCurPath=TcpClient::getInstance().curPath();
    QListWidgetItem *pItem=m_pBookListW->currentItem();
    if(pItem==NULL){
        QMessageBox::warning(this,"删除文件","请选择要删除的文件");
    }
    else{
        QString strDelName=pItem->text();
        PDU *pdu=mkPDU(strCurPath.size()+1);
        pdu->uiMsgType=ENUM_MSG_TYPE_DEL_DIR_REQUEST;
        strncpy(pdu->caData,strDelName.toStdString().c_str(),strDelName.size());
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu=NULL;
    }
}

void Book::renameFile(){
    //当前路径
    QString strCurPath=TcpClient::getInstance().curPath();
    //列表上获得要重命名的文件
    QListWidgetItem *pItem=m_pBookListW->currentItem();
    if(pItem==NULL){
        QMessageBox::warning(this,"重命名文件","请选择要删除重命名的文件");
    }
    else{
        QString strOldName=pItem->text();
        //通过对话框直接输入新文件名
        QString strNewName=QInputDialog::getText(this,"重命名文件","请输入新的文件名");
        if(!strNewName.isEmpty()){
            PDU *pdu=mkPDU(strCurPath.size()+1);
            pdu->uiMsgType=ENUM_MSG_TYPE_RENAME_FILE_REQUEST;
            strncpy(pdu->caData,strOldName.toStdString().c_str(),strOldName.size());
            strncpy(pdu->caData+32,strNewName.toStdString().c_str(),strNewName.size());
            memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
            TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
            free(pdu);
            pdu=NULL;
        }
        else{
            QMessageBox::warning(this,"重命名文件","新文件名不能为空");
        }
    }
}

void Book::enterDir(const QModelIndex &index){
    //获得文件名 当前路径
    QString strDirName=index.data().toString();
    m_strEnterDir=strDirName;
    QString strCurPath=TcpClient::getInstance().curPath();
    PDU *pdu=mkPDU(strCurPath.size()+1);
    pdu->uiMsgType=ENUM_MSG_TYPE_ENTER_DIR_REQUEST;
    strncpy(pdu->caData,strDirName.toStdString().c_str(),strDirName.size());
    memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());

    qDebug()<<strDirName;

    TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
    free(pdu);
    pdu=NULL;
}

void Book::returnPre(){
    QString strCurPath=TcpClient::getInstance().curPath();
    QString strRootPath="./"+TcpClient::getInstance().loginName();
    if(strCurPath==strRootPath){
        QMessageBox::warning(this,"返回","返回失败：已经在最开始的目录");
    }
    else{
        //生成上一级目录路径
        int index=strCurPath.lastIndexOf('/');
        strCurPath.remove(index,strCurPath.size()-index);
        qDebug()<<"return -->"<<strCurPath;
        TcpClient::getInstance().setCurPath(strCurPath);
        //发送前清空目录?
        clearEnterDir();

        //向服务器发送刷新的请求
        flushFile();
    }
}

void Book::uploadFile()
{
    //获得当前所在的路径
    QString strCurPath=TcpClient::getInstance().curPath();
    //弹出对话框，选择文件后返回路径
    m_strUploadFilePath=QFileDialog::getOpenFileName();
    qDebug()<<m_strUploadFilePath;
    if(!m_strUploadFilePath.isEmpty()){
        //从后往前找/符号
        int index=m_strUploadFilePath.lastIndexOf('/');
        //此处向右提取定长字符
        QString strFileName=m_strUploadFilePath.right(m_strUploadFilePath.size()-index-1);
        qDebug()<<strFileName;
        QFile file(m_strUploadFilePath);
        qint64 fileSize=file.size();    //获得文件大小

        PDU *pdu=mkPDU(strCurPath.size()+1);
        pdu->uiMsgType=ENUM_MSG_TYPE_UPLOAD_FILE_REQUEST;
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        //格式化数据写入字符串中
        sprintf(pdu->caData,"%s %lld",strFileName.toStdString().c_str(),fileSize);

        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu=NULL;

        m_pTimer->start(1000);  //给1s
    }
    else{
        QMessageBox::warning(this,"上传文件","上传文件名字不能为空!");
    }
}

void Book::uploadFileData()
{
    m_pTimer->stop();
    QFile file(m_strUploadFilePath);
    //尝试打开指定路径文件
    if(!file.open(QIODevice::ReadOnly)){
        QMessageBox::warning(this,"上传文件","打开文件失败!");
        return;
    }
    char *pBuffer=new char[4096];   //4096字节的读取，其速率较高
    qint64 ret=0;
    while(true){
        ret=file.read(pBuffer,4096);
        if(ret>0&&ret<=4096){
            //客户端根据读取的数据量发送数据
            TcpClient::getInstance().getTcpSocket().write(pBuffer,ret);
        }
        else if(ret==0){
            break;
        }
        else{
            QMessageBox::warning(this,"上传文件","文件上传失败：读文件失败");
            break;
        }
    }
    file.close();
    delete []pBuffer;
    pBuffer=NULL;
}

void Book::delRegFile()
{
    QString strCurPath=TcpClient::getInstance().curPath();
    QListWidgetItem *pItem=m_pBookListW->currentItem();
    if(pItem==NULL){
        QMessageBox::warning(this,"删除文件","请选择要删除的文件");
    }
    else{
        QString strDelName=pItem->text();
        PDU *pdu=mkPDU(strCurPath.size()+1);
        pdu->uiMsgType=ENUM_MSG_TYPE_DEL_FILE_REQUEST;
        strncpy(pdu->caData,strDelName.toStdString().c_str(),strDelName.size());
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu=NULL;
    }
}

void Book::downloadFile()
{
    QListWidgetItem *pItem=m_pBookListW->currentItem();
    if(pItem==NULL){
        QMessageBox::warning(this,"下载文件","请选择要下载的文件");
    }
    else{
        //获得要保存的路径
        QString strSaveFilePath=QFileDialog::getSaveFileName();
        if(strSaveFilePath.isEmpty()){
            QMessageBox::warning(this,"下载文件","请指定要保存的位置");
            m_strSaveFilePath.clear();
        }
        else{
            //地址不为空，则记录地址
            m_strSaveFilePath=strSaveFilePath;
            //m_bDownload=true;
        }
        qDebug()<<m_strSaveFilePath;
        //发送路径和文件名
        QString strCurPath=TcpClient::getInstance().curPath();
        PDU *pdu=mkPDU(strCurPath.size()+1);
        pdu->uiMsgType=ENUM_MSG_TYPE_DOWNLOAD_FILE_REQUEST;
        QString strFileName=pItem->text();
        strcpy(pdu->caData,strFileName.toStdString().c_str());
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu=NULL;
    }

}

void Book::shareFile()
{
    //获得当前选项
    QListWidgetItem *pItem=m_pBookListW->currentItem();
    if(pItem==NULL){
        QMessageBox::warning(this,"分享文件","请选择要分享的文件");
        return;
    }
    else{
        m_strShareFileName=pItem->text();
    }

    Friend *pFriend=OpeWidget::getInstance().getFriend();   //获得好友类
    QListWidget *pFriendList=pFriend->getFriendList();  //好友列表
    ShareFile::getInstance().updateFriend(pFriendList); //更新显示
    //显示弹窗
    if(ShareFile::getInstance().isHidden()){
        ShareFile::getInstance().show();
    }
}

void Book::moveFile()
{
    QListWidgetItem *pCurItem=m_pBookListW->currentItem();
    if(pCurItem!=NULL){
        m_strMoveFileName=pCurItem->text();
        QString strCurPath=TcpClient::getInstance().curPath();
        m_strMoveFilePath=strCurPath+'/'+m_strMoveFileName;

        m_SelectDirPB->setEnabled(true);
    }
    else{
        QMessageBox::warning(this,"移动文件","请选择要移动的文件");
    }
}

void Book::selectDestDir()
{
    QListWidgetItem *pCurItem=m_pBookListW->currentItem();
    if(pCurItem!=NULL){
        QString strDestDir=pCurItem->text();
        QString strCurPath=TcpClient::getInstance().curPath();
        m_strDestDir=strCurPath+'/'+strDestDir;

        int srcLen=m_strMoveFilePath.size();
        int destLen=m_strDestDir.size();
        PDU *pdu=mkPDU(srcLen+destLen+2);
        pdu->uiMsgType=ENUM_MSG_TYPE_MOVE_FILE_REQUEST;
        sprintf(pdu->caData,"%d %d %s",srcLen,destLen,m_strMoveFileName.toStdString().c_str());

        memcpy(pdu->caMsg,m_strMoveFilePath.toStdString().c_str(),srcLen);
        memcpy((char*)pdu->caMsg+srcLen+1,m_strDestDir.toStdString().c_str(),destLen);
        qDebug()<<m_strMoveFilePath<<m_strDestDir;

        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu=NULL;

    }
    else{
        QMessageBox::warning(this,"移动文件","请选择要移动的文件");
    }
    m_SelectDirPB->setEnabled(false);
}

void Book::setDownloadFlag(bool status)
{
    m_bDownload=status;
}

bool Book::getDownloadFlag(){
    return m_bDownload;
}

QString Book::getSaveFilePath(){
    return m_strSaveFilePath;
}

QString Book::getShareFileName()
{
    return m_strShareFileName;
}
